﻿/**************************************************************************************
*
* Filename: IMetaDataDocument.cs
* Description: mdle sdk
* Author: Xinchang Wang
* Company: Nanjing Normal University OpenGMS
* Date: 2018/10/17
*
**************************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

namespace nxmodel.mdl.csharp
{
    public class SpatiotemporalInfo : ISpatiotemporalInfo
    {
        private bool _isSpatailInfoEnabled;
        private List<string> _spatialDimensions = new List<string>();
        private ESpatialScale _spatialScale = new ESpatialScale();
        private string _spatialScaleDescription;
        private ESpatialReferenceType _spatialReferenceType = new ESpatialReferenceType();
        private string _spatialReferenceWKT;
        private List<SpatialTemporalStepItem> _spatialResolutionItems = new List<SpatialTemporalStepItem>();
        private List<SpatialExtentItem> _spatialExtents = new List<SpatialExtentItem>();
        private bool _temproalInfoEnabled;
        private ETemporalScale _timeScaleType = new ETemporalScale();
        private string _timeScaleDescription;
        private ETimeReferenceType _timeReferenceType = new ETimeReferenceType();
        private string _timeReferenceValue;
        private List<SpatialTemporalStepItem> _timeStepItems = new List<SpatialTemporalStepItem>();
        private List<TimeExtentItem> _timeExtents = new List<TimeExtentItem>();

        public bool SpatailInfoEnabled
        {
            get
            {
                return this._isSpatailInfoEnabled;
            }
            set
            {
                this._isSpatailInfoEnabled = value;
            }
        }

        public string getSpatialDimension(int index)
        {
            if (index > this._spatialDimensions.Count || index < 0)
            {
                //return null;
                throw new IndexOutOfRangeException();
            }
            return this._spatialDimensions[index];
        }

        public int SpatialDimensionsCount
        {
            get { return this._spatialDimensions.Count; }
        }

        public int insertDimension(string dimesion)
        {
            this._spatialDimensions.Add(dimesion);
            return 1;
        }

        public int removeDimension(int index)
        {
            if (index > this._spatialDimensions.Count || index < 0)
            {
                //return -1;
                throw new IndexOutOfRangeException();
            }
            this._spatialDimensions.RemoveAt(index);
            return 1;
        }

        public ESpatialScale SpatialScaleType
        {
            get
            {
                return this._spatialScale;
            }
            set
            {
                this._spatialScale = value;
            }
        }

        public string SpatialScaleDescription
        {
            get
            {
                return this._spatialScaleDescription;
            }
            set
            {
                this._spatialScaleDescription = value;
            }
        }

        public ESpatialReferenceType SpatialReferenceType
        {
            get
            {
                return this._spatialReferenceType;
            }
            set
            {
                this._spatialReferenceType = value;
            }
        }

        public string SpatialReferenceWKT
        {
            get
            {
                return this._spatialReferenceWKT;
            }
            set
            {
                this._spatialReferenceWKT = value;
            }
        }
        
        public SpatialTemporalStepItem getSpatialResolutionItem(int index)
        {
            if (index > this._spatialResolutionItems.Count || index < 0)
            {
                //return new SpatialTemporalStepItem();
                throw new IndexOutOfRangeException();
            }
            return this._spatialResolutionItems[index];
        }

        public int SpatialResolutionItemCount
        {
            get { return this._spatialResolutionItems.Count; }
        }

        public int insertSpatialResolutionItem(SpatialTemporalStepItem item)
        {
            this._spatialResolutionItems.Add(item);
            return 1;
        }

        public int removeSpatialResolutionItem(int index)
        {
            if (index > this._spatialResolutionItems.Count || index < 0)
            {
                //return -1;
                throw new IndexOutOfRangeException();
            }
            this._spatialResolutionItems.RemoveAt(index);
            return 1;
        }

        public SpatialExtentItem getSpatialExtent(int index)
        {
            if (index > this._spatialExtents.Count || index < 0)
            {
                //return new SpatialExtent();
                throw new IndexOutOfRangeException();
            }
            return this._spatialExtents[index];
        }

        public int SpatialExtentsCount
        {
            get { return this._spatialExtents.Count; }
        }

        public int insertSpatialExtent(SpatialExtentItem extent)
        {
            this._spatialExtents.Add(extent);
            return 1;
        }

        public int removeSpatialExtent(int index)
        {
            if (index > this._spatialExtents.Count || index < 0)
            {
                //return -1;
                throw new IndexOutOfRangeException();
            }
            this._spatialExtents.RemoveAt(index);
            return 1;
        }

        public bool TemproalInfoEnabled
        {
            get
            {
                return this._temproalInfoEnabled;
            }
            set
            {
                this._temproalInfoEnabled = value;
            }
        }

        public ETemporalScale TimeScaleType
        {
            get
            {
                return this._timeScaleType;
            }
            set
            {
                this._timeScaleType = value;
            }
        }

        public string TimeScaleDescription
        {
            get
            {
                return this._timeScaleDescription;
            }
            set
            {
                this._timeScaleDescription = value;
            }
        }

        public ETimeReferenceType TimeReferenceType
        {
            get
            {
                return this._timeReferenceType;
            }
            set
            {
                this._timeReferenceType = value;
            }
        }
        
        public string TimeReferenceValue
        {
            get
            {
                return this._timeReferenceValue;
            }
            set
            {
                this._timeReferenceValue = value;
            }
        }
        
        public SpatialTemporalStepItem getTimeStepItem(int index)
        {
            if (index > this._timeStepItems.Count || index < 0)
            {
                //return new SpatialTemporalStepItem();
                throw new IndexOutOfRangeException();
            }
            return this._timeStepItems[index];
        }

        public int TimeStepItemCount
        {
            get { return this._timeStepItems.Count; }
        }

        public int insertTimeStepItem(SpatialTemporalStepItem item)
        {
            this._timeStepItems.Add(item);
            return 1;
        }

        public int removeTimeStepItem(int index)
        {
            if (index > this._timeStepItems.Count || index < 0)
            {
                //return -1;
                throw new IndexOutOfRangeException();
            }
            this._timeStepItems.RemoveAt(index);
            return 1;
        }

        public TimeExtentItem getTimeExtent(int index)
        {
            if (index > this._timeExtents.Count || index < 0)
            {
                //return new TimeExtentItem();
                throw new IndexOutOfRangeException();
            }
            return this._timeExtents[index];
        }

        public int TimeExtentsCount
        {
            get { return this._timeExtents.Count; }
        }

        public int insertTimeExtent(TimeExtentItem item)
        {
            this._timeExtents.Add(item);
            return 1;
        }

        public int removeTimeExtent(int index)
        {
            if (index > this._timeExtents.Count || index < 0)
            {
                //return -1;
                throw new IndexOutOfRangeException();
            }
            this._timeExtents.RemoveAt(index);
            return 1;
        }

        public bool formatToXml(ref XmlElement basicMetaDataEle)
        {
            XmlDocument doc = basicMetaDataEle.OwnerDocument;
            XmlElement spatiotemporalInfoEle = doc.CreateElement("SpatiotemporalInfo");
            basicMetaDataEle.AppendChild(spatiotemporalInfoEle);

            //SpatialExtents
            XmlElement spatialInfoEle = doc.CreateElement("SpatialInfo");
            string spatialEnable = this._isSpatailInfoEnabled == true ? "true" : "false";
            spatialInfoEle.SetAttribute("enable", spatialEnable);
            spatiotemporalInfoEle.AppendChild(spatialInfoEle);

            if (spatialEnable == "true")
            {
                
                XmlElement spatialDimensionRoot = doc.CreateElement("SpatialDimension");
                for (int i = 0; i < this._spatialDimensions.Count; i++)
                {
                    XmlElement spatialDimensionEle = doc.CreateElement("Add");
                    spatialDimensionEle.SetAttribute("value", this._spatialDimensions[i]);
                    spatialDimensionRoot.AppendChild(spatialDimensionEle);
                }
                spatialInfoEle.AppendChild(spatialDimensionRoot);


                XmlElement scaleEle = doc.CreateElement("Scale");
                string spatialscaleType = this._spatialScale.ToString();
                spatialscaleType = spatialscaleType.Substring(spatialscaleType.IndexOf('_') + 1);
                scaleEle.SetAttribute("type", spatialscaleType);
                scaleEle.SetAttribute("description", this._spatialScaleDescription);
                spatialInfoEle.AppendChild(scaleEle);

                XmlElement spatialReferenceEle = doc.CreateElement("SpatialReference");
                string referenceGeneral = this._spatialReferenceType.ToString();
                referenceGeneral = referenceGeneral.Substring(referenceGeneral.IndexOf('_') + 1);
                spatialReferenceEle.SetAttribute("general", referenceGeneral);
                spatialReferenceEle.SetAttribute("wkt", this._spatialReferenceWKT);
                spatialInfoEle.AppendChild(spatialReferenceEle);

                XmlElement resolutionConstraintRoot = doc.CreateElement("ResolutionConstraint");
                for (int i = 0; i < this._spatialResolutionItems.Count; i++)
                {
                    XmlElement resolutionConstraintEle = doc.CreateElement("Add");
                    resolutionConstraintEle.SetAttribute("name", this._spatialResolutionItems[i].Key);
                    resolutionConstraintEle.SetAttribute("value", this._spatialResolutionItems[i].Value);
                    resolutionConstraintEle.SetAttribute("unit", this._spatialResolutionItems[i].Unit);
                    resolutionConstraintRoot.AppendChild(resolutionConstraintEle);
                }
                spatialInfoEle.AppendChild(resolutionConstraintRoot);


                XmlElement spatialExtentsRoot = doc.CreateElement("SpatialExtents");
                for (int i = 0; i < this._spatialExtents.Count; i++)
                {
                    XmlElement spatialExtentEle = doc.CreateElement("Add");
                    string spatialExtentType = this._spatialExtents[i].Type.ToString();
                    spatialExtentType = spatialExtentType.Substring(spatialExtentType.IndexOf('_') + 1);
                    spatialExtentEle.SetAttribute("type", spatialExtentType);
                    spatialExtentEle.SetAttribute("name", this._spatialExtents[i].Name);
                    spatialExtentEle.SetAttribute("value", this._spatialExtents[i].Value);
                    spatialExtentEle.SetAttribute("spatialReference", this._spatialExtents[i].SReference);
                    spatialExtentsRoot.AppendChild(spatialExtentEle);
                }
                spatialInfoEle.AppendChild(spatialExtentsRoot);

            }

            //TemporalInfo
            XmlElement temporalInfoEle = doc.CreateElement("TemporalInfo");
            string temporaEnable = this._temproalInfoEnabled == true ? "true" : "false";
            temporalInfoEle.SetAttribute("enable", temporaEnable);
            spatiotemporalInfoEle.AppendChild(temporalInfoEle);

            if (temporaEnable == "true")
            {
                XmlElement temporaScaleEle = doc.CreateElement("Scale");
                string temporaScaleType = this.TimeScaleType.ToString();
                temporaScaleType = temporaScaleType.Substring(temporaScaleType.IndexOf('_') + 1);
                temporaScaleEle.SetAttribute("type", temporaScaleType);
                temporaScaleEle.SetAttribute("description", this.TimeScaleDescription);
                temporalInfoEle.AppendChild(temporaScaleEle);

                XmlElement timeReferenceEle = doc.CreateElement("TimeReference");
                string timeReferenceType = this.TimeReferenceType.ToString();
                timeReferenceType = timeReferenceType.Substring(timeReferenceType.IndexOf('_') + 1);
                timeReferenceEle.SetAttribute("type", timeReferenceType);
                timeReferenceEle.SetAttribute("value", this.TimeReferenceValue);
                temporalInfoEle.AppendChild(timeReferenceEle);

                XmlElement stepConstraintRoot = doc.CreateElement("StepConstraint");
                stepConstraintRoot.InnerText = "";
                for (int i = 0; i < this._timeStepItems.Count; i++)
                {
                    XmlElement stepConstraintEle = doc.CreateElement("Add");
                    stepConstraintEle.SetAttribute("name", this._timeStepItems[i].Key);
                    stepConstraintEle.SetAttribute("value", this._timeStepItems[i].Value);
                    stepConstraintEle.SetAttribute("unit", this._timeStepItems[i].Unit);
                    stepConstraintRoot.AppendChild(stepConstraintEle);
                }
                temporalInfoEle.AppendChild(stepConstraintRoot);

                XmlElement timeExtentsRoot = doc.CreateElement("TimeExtents");
                timeExtentsRoot.InnerText = "";
                for (int i = 0; i < this._timeExtents.Count; i++)
                {
                    XmlElement timeExtentEle = doc.CreateElement("Add");
                    string timeExtentType = this._timeExtents[i].Type.ToString();
                    timeExtentType = timeExtentType.Substring(timeExtentType.IndexOf('_') + 1);
                    timeExtentEle.SetAttribute("type", timeExtentType);
                    timeExtentEle.SetAttribute("name", this._timeExtents[i].Name);
                    timeExtentEle.SetAttribute("value", this._timeExtents[i].Value);
                    timeExtentEle.SetAttribute("unit", this._timeExtents[i].Unit);
                    timeExtentsRoot.AppendChild(timeExtentEle);
                }
                temporalInfoEle.AppendChild(timeExtentsRoot);
            }

            return true;
        }

        public bool loadXml(XmlElement spatiotemporalInfoEle)
        {
            XmlElement spatialInfoEle = (XmlElement)spatiotemporalInfoEle.SelectSingleNode("SpatialInfo");
            string spatialEnabled = spatialInfoEle.GetAttribute("enable");
            this._isSpatailInfoEnabled = spatialEnabled == "true" ? true : false;
            if (this._isSpatailInfoEnabled == true)
            {
                //dimension
                XmlElement dimensionRoot = (XmlElement)spatialInfoEle.SelectSingleNode("SpatialDimension");
                foreach (XmlNode dimensionNode in dimensionRoot.ChildNodes)
                {
                    XmlElement dimensionEle = (XmlElement)dimensionNode;
                    string value = dimensionEle.GetAttribute("value");
                    this._spatialDimensions.Add(value);
                }

                //scale
                XmlElement scaleEle = (XmlElement)spatialInfoEle.SelectSingleNode("Scale");
                string strScaleType = scaleEle.GetAttribute("type");
                string scaleDescription = scaleEle.GetAttribute("description");
                ESpatialScale scaleType = new ESpatialScale();
                foreach (ESpatialScale eType in Enum.GetValues(typeof(ESpatialScale)))
                {
                    string strSType = eType.ToString();
                    strSType = strSType.Substring(strSType.IndexOf('_') + 1);
                    if (strSType == strScaleType)
                    {
                        scaleType = eType;
                        break;
                    }
                }
                
                this._spatialScale = scaleType;
                this._spatialScaleDescription=scaleDescription;


                //reference
                XmlElement referenceEle = (XmlElement)spatialInfoEle.SelectSingleNode("SpatialReference");
                string strGeneral = referenceEle.GetAttribute("general");
                string wkt = referenceEle.GetAttribute("wkt");
                ESpatialReferenceType general = new ESpatialReferenceType();
                foreach (ESpatialReferenceType eType in Enum.GetValues(typeof(ESpatialReferenceType)))
                {
                    string strEType = eType.ToString();
                    strEType = strEType.Substring(strEType.IndexOf('_') + 1);
                    if (strGeneral == strEType)
                    {
                        general = eType;
                        break;
                    }
                }
                this._spatialReferenceType = general;
                this._spatialReferenceWKT = wkt;

                //resolution
                XmlElement resolutionRoot = (XmlElement)spatialInfoEle.SelectSingleNode("ResolutionConstraint");
                foreach (XmlNode resolutionNode in resolutionRoot.ChildNodes)
                {
                    XmlElement resolutionEle = (XmlElement)resolutionNode;
                    string name = resolutionEle.GetAttribute("name");
                    string value = resolutionEle.GetAttribute("value");
                    string unit = resolutionEle.GetAttribute("unit");
                    SpatialTemporalStepItem sti = new SpatialTemporalStepItem(name,value,unit);
                    this._spatialResolutionItems.Add(sti);
                }

                //spatialExtents
                XmlElement extentRoot = (XmlElement)spatialInfoEle.SelectSingleNode("SpatialExtents");
                foreach (XmlNode extentNode in extentRoot.ChildNodes)
                {
                    XmlElement extentEle = (XmlElement)extentNode;
                    string strType = extentEle.GetAttribute("type");
                    string name = extentEle.GetAttribute("name");
                    string value = extentEle.GetAttribute("value");
                    string reference = extentEle.GetAttribute("spatialReference");
                    EExtentType type = new EExtentType();
                    foreach (EExtentType eType in Enum.GetValues(typeof(EExtentType)))
                    {
                        string strEType = eType.ToString();
                        strEType = strEType.Substring(strEType.IndexOf('_') + 1);
                        if (strEType == strType)
                        {
                            type = eType;
                            break;
                        }
                    }
                    SpatialExtentItem sei = new SpatialExtentItem(name, type, value, reference);
                    this._spatialExtents.Add(sei);
                }

            }

            XmlElement temporalInfoEle = (XmlElement)spatiotemporalInfoEle.SelectSingleNode("TemporalInfo");
            string temporalEnbaled = temporalInfoEle.GetAttribute("enable");
            this._temproalInfoEnabled = temporalEnbaled == "true" ? true : false;
            if (this._temproalInfoEnabled == true)
            {
                //Scale
                XmlElement scaleEle = (XmlElement)temporalInfoEle.SelectSingleNode("Scale");
                string strScaleType = scaleEle.GetAttribute("type");
                string scaleDescription = scaleEle.GetAttribute("description");
                ETemporalScale scaleType = new ETemporalScale();
                foreach (ETemporalScale eType in Enum.GetValues(typeof(ETemporalScale)))
                {
                    string strSType = eType.ToString();
                    strSType = strSType.Substring(strSType.IndexOf('_') + 1);
                    if (strSType == strScaleType)
                    {
                        scaleType = eType;
                        break;
                    }
                }
                this._timeScaleDescription = scaleDescription;
                this._timeScaleType = scaleType;

                //reference
                XmlElement referenceEle = (XmlElement)temporalInfoEle.SelectSingleNode("TimeReference");
                string strRefType = referenceEle.GetAttribute("type");
                string refValue = referenceEle.GetAttribute("value");
                ETimeReferenceType refType = new ETimeReferenceType();
                foreach (ETimeReferenceType eType in Enum.GetValues(typeof(ETimeReferenceType)))
                {
                    string strRType = eType.ToString();
                    strRType = strRType.Substring(strRType.IndexOf('_') + 1);
                    if (strRType == strRefType)
                    {
                        refType = eType;
                        break;
                    }
                }
                this._timeReferenceType = refType;
                this._timeReferenceValue = refValue;

                //step
                XmlElement stepRoot = (XmlElement)temporalInfoEle.SelectSingleNode("StepConstraint");
                foreach (XmlNode stepNode in stepRoot.ChildNodes)
                {
                    XmlElement stepEle = (XmlElement)stepNode;
                    string name = stepEle.GetAttribute("name");
                    string value = stepEle.GetAttribute("value");
                    string unit = stepEle.GetAttribute("unit");
                    SpatialTemporalStepItem stsi = new SpatialTemporalStepItem(name, value, unit);
                    this._timeStepItems.Add(stsi);
                }

                //extent
                XmlElement extentsRoot = (XmlElement)temporalInfoEle.SelectSingleNode("TimeExtents");
                foreach (XmlNode extentNode in extentsRoot.ChildNodes)
                {
                    XmlElement extentEle = (XmlElement)extentNode;
                    string name = extentEle.GetAttribute("name");
                    string value = extentEle.GetAttribute("value");
                    string unit = extentEle.GetAttribute("unit");
                    string strType = extentEle.GetAttribute("type");
                    ETimeExtentItemType type = new ETimeExtentItemType();
                    foreach (ETimeExtentItemType etype in Enum.GetValues(typeof(ETimeExtentItemType)))
                    {
                        string strEType = etype.ToString();
                        strEType = strEType.Substring(strEType.IndexOf('_') + 1);
                        if (strEType == strType)
                        {
                            type = etype;
                            break;
                        }
                    }
                    TimeExtentItem tei = new TimeExtentItem(name, type, value, unit);
                    this._timeExtents.Add(tei);
                }


            }

            return true;
        }


    }

    public class Contributor : IContributor
    {
        private string _name;
        private string _account;
        private ContributorInstitution _institution = new ContributorInstitution();
        private List<ContributorRoleItem> _contributorRoleItems = new List<ContributorRoleItem>();
        private List<ContributorContactItem> _contacts = new List<ContributorContactItem>();

        public string Name
        {
            get
            {
                return this._name;
            }
            set
            {
                this._name = value;
            }
        }

        public string Account
        {
            get
            {
                return this._account;
            }
            set
            {
                this._account = value;
            }
        }

        public ContributorInstitution Institution
        {
            get
            {
                return this._institution;
            }
            set
            {
                this._institution = value;
            }
        }

        public ContributorRoleItem getRole(int index)
        {
            if (index > this._contributorRoleItems.Count || index < 0)
            {
                throw new IndexOutOfRangeException();
            }
            return this._contributorRoleItems[index];
        }

        public int RolesCount
        {
            get { return this._contributorRoleItems.Count; }
        }

        public int insertRole(ContributorRoleItem role)
        {
            this._contributorRoleItems.Add(role);
            return 1;
        }

        public int removeRole(int index)
        {
            if (index > this._contributorRoleItems.Count || index < 0)
            {
                throw new IndexOutOfRangeException();
            }
            this._contributorRoleItems.RemoveAt(index);
            return 1;
        }

        public ContributorContactItem getContact(int index)
        {
            if (index > this._contacts.Count || index < 0)
            {
                throw new IndexOutOfRangeException();
            }
            return this._contacts[index];
        }

        public int ContactsCount
        {
            get { return this._contacts.Count; }
        }

        public int insertContact(ContributorContactItem item)
        {
            this._contacts.Add(item);
            return 1;
        }

        public int removeContact(int index)
        {
            if (index > this._contacts.Count || index < 0)
            {
                throw new IndexOutOfRangeException();
            }
            this._contacts.RemoveAt(index);
            return 1;
        }

        public bool formatToXml(ref XmlElement contributorsEle)
        {
            XmlDocument doc = contributorsEle.OwnerDocument;
            XmlElement contributorEle = doc.CreateElement("Contributor");

            //Note: the difference between contributorsEle and contributorEle
            contributorEle.SetAttribute("name", this._name);
            contributorEle.SetAttribute("account", this._account);
            contributorsEle.AppendChild(contributorEle);

            XmlElement institutionEle = doc.CreateElement("Institution");
            institutionEle.SetAttribute("name", this._institution.Name);
            institutionEle.SetAttribute("country", this._institution.Country);
            institutionEle.SetAttribute("city", this._institution.City);
            institutionEle.SetAttribute("address", this._institution.Address);
            contributorEle.AppendChild(institutionEle);

            XmlElement contributionRoleRoot = doc.CreateElement("ContributionRole");
            for (int i = 0; i < this._contributorRoleItems.Count; i++)
            {
                XmlElement contributionRoleEle = doc.CreateElement("Add");
                string value = this._contributorRoleItems[i].Role.ToString();
                value = value.Substring(value.IndexOf('_')+1);
                contributionRoleEle.SetAttribute("value", value);
                contributionRoleEle.SetAttribute("description", this._contributorRoleItems[i].Description);
                contributionRoleRoot.AppendChild(contributionRoleEle);
            }
            contributorEle.AppendChild(contributionRoleRoot);

            XmlElement contactsRoot = doc.CreateElement("Contacts");
            for (int i = 0; i < this._contacts.Count; i++)
            {
                XmlElement contactEle = doc.CreateElement("Add");
                string type = this._contacts[i].Type.ToString();
                type = type.Substring(type.IndexOf('_') + 1);
                contactEle.SetAttribute("type", type);
                contactEle.SetAttribute("value", this._contacts[i].Value);
                contactsRoot.AppendChild(contactEle);
            }
            contributorEle.AppendChild(contactsRoot);

            return true;

        }

        public bool loadXml(XmlElement contributorEle)
        {
            string name = contributorEle.GetAttribute("name");
            string account = contributorEle.GetAttribute("account");
            this._name = name;
            this._account = account;

            //institution
            XmlElement institutionEle = (XmlElement)contributorEle.SelectSingleNode("Institution");
            string institutionName = institutionEle.GetAttribute("name");
            string country = institutionEle.GetAttribute("country");
            string city = institutionEle.GetAttribute("city");
            string address = institutionEle.GetAttribute("address");
            ContributorInstitution ci = new ContributorInstitution(institutionName, country, city, address);
            this._institution = ci;

            //contributionRole
            XmlElement roleRootEle = (XmlElement)contributorEle.SelectSingleNode("ContributionRole");
            foreach (XmlNode roleNode in roleRootEle.ChildNodes)
            {
                XmlElement roleEle = (XmlElement)roleNode;
                string description = roleEle.GetAttribute("description");
                string strValue = roleEle.GetAttribute("value");
                EContributorRoleType value = new EContributorRoleType();
                foreach(EContributorRoleType ecType in Enum.GetValues(typeof(EContributorRoleType)))
                {
                    string cStrType = ecType.ToString();
                    cStrType = cStrType.Substring(cStrType.IndexOf('_')+1);
                    if(cStrType==strValue)
                    {
                        value = ecType;
                        break;
                    }
                }
                ContributorRoleItem cri = new ContributorRoleItem(value,description);
                this._contributorRoleItems.Add(cri);
            }

            //contacts
            XmlElement contactsRoot = (XmlElement)contributorEle.SelectSingleNode("Contacts");
            foreach (XmlNode contactNode in contactsRoot.ChildNodes)
            {
                XmlElement contactEle = (XmlElement)contactNode;
                string strType = contactEle.GetAttribute("type");
                string value = contactEle.GetAttribute("value");
                EContributorContactType type = new EContributorContactType();                
                foreach (EContributorContactType eType in Enum.GetValues(typeof(EContributorContactType)))
                {
                    string cStrType = eType.ToString();
                    cStrType = cStrType.Substring(cStrType.IndexOf('_') + 1);
                    if (strType == cStrType)
                    {
                        type = eType;
                        break;
                    }
                }
                ContributorContactItem cci = new ContributorContactItem(type, value);
                this._contacts.Add(cci);
                
            }

            return true;
        }
    }

    public class BasicMeta : IBasicMeta
    {

        private List<string> _alias = new List<string>();
        private List<string> _domains = new List<string>();
        private List<MechanismItem> _mechanismItems = new List<MechanismItem>();
        private List<MethodItem> _methodItems = new List<MethodItem>();
        private List<Contributor> _contributors = new List<Contributor>();
        private List<ComponentItem> _componentItems = new List<ComponentItem>();
        private List<ProcessingItem> _processingItems = new List<ProcessingItem>();
        private List<EProgrammingLanguage> _programmingLanguages = new List<EProgrammingLanguage>();
        private List<PotentialCouplingComponent> _potentialComponents = new List<PotentialCouplingComponent>();
        private SpatiotemporalInfo _spatialtemporalInfos = new SpatiotemporalInfo();

        public string getAlias(int index)
        {
            if (index > this._alias.Count || index < 0)
            {
                //return null;
                throw new IndexOutOfRangeException();
            }
            return this._alias[index];
        }

        public int AliasCount
        {
            get { return this._alias.Count; }
        }

        public int insertAlias(string alias)
        {
            this._alias.Add(alias);
            return 1;
        }

        public int removeAlias(int index)
        {
            if (index > this._alias.Count || index < 0)
            {
                //return -1;
                throw new IndexOutOfRangeException();
            }
            this._alias.RemoveAt(index);
            return 1;
        }

        public string getDomain(int index)
        {
            if (index > this._domains.Count || index < 0)
            {
                //return null;
                throw new IndexOutOfRangeException();
            }
            return this._domains[index];
        }

        public int DomainsCount
        {
            get { return this._domains.Count; }
        }

        public int insertDomain(string domain)
        {
            this._domains.Add(domain);
            return 1;
        }

        public int removeDomain(int index)
        {
            if (index > this._domains.Count || index < 0)
            {
                //return -1;
                throw new IndexOutOfRangeException();
            }
            this._domains.RemoveAt(index);
            return 1;
        }

        public MechanismItem getMechanism(int index)
        {
            if (index > this._mechanismItems.Count || index < 0)
            {
                //return new MechanismItem();
                throw new IndexOutOfRangeException();
            }
            return this._mechanismItems[index];
        }

        public int MechanismCount
        {
            get { return this._mechanismItems.Count; }

        }

        public int insertMechanism(MechanismItem item)
        {
            this._mechanismItems.Add(item);
            return 1;
        }

        public int removeMechanism(int index)
        {
            if (index > this._mechanismItems.Count || index < 0)
            {
                //return -1;
                throw new IndexOutOfRangeException();
            }
            this._mechanismItems.RemoveAt(index);
            return 1;
        }

        public MethodItem getMethod(int index)
        {
            if (index > this._methodItems.Count || index < 0)
            {
                //return new MethodItem();
                throw new IndexOutOfRangeException();
            }
            return this._methodItems[index];
        }

        public int MethodsCount
        {
            get { return this._methodItems.Count; }
        }

        public int insertMethod(MethodItem item)
        {
            this._methodItems.Add(item);
            return 1;
        }

        public int removeMethod(int index)
        {
            if (index > this._methodItems.Count || index < 0)
            {
                //return -1;
                throw new IndexOutOfRangeException();
            }
            this._methodItems.RemoveAt(index);
            return 1;
        }

        public ISpatiotemporalInfo getSpatiotemporalInfo()
        {
            return this._spatialtemporalInfos;
        }
        
        public IContributor getContributor(int index)
        {
            if (index > this._contributors.Count || index < 0)
            {
                //return null;
                throw new IndexOutOfRangeException();
            }
            return this._contributors[index];
        }
        
        public int ContributorsCount
        {
            get { return this._contributors.Count; }
        }

        public int insertContributor(Contributor item)
        {
            this._contributors.Add(item);
            return 1;
        }

        public int removeContributor(int index)
        {
            if (index > this._contributors.Count || index < 0)
            {
                //return -1;
                throw new IndexOutOfRangeException();
            }
            this._contributors.RemoveAt(index);
            return 1;
        }

        public ComponentItem getComponent(int index)
        {
            if (index > this._componentItems.Count || index < 0)
            {
                //return new ComponentItem();
                throw new IndexOutOfRangeException();
            }
            return this._componentItems[index];
        }

        public int ComponentsCount
        {
            get { return this._componentItems.Count; }
        }

        public int insertComponent(ComponentItem item)
        {
            this._componentItems.Add(item);
            return 1;
        }

        public int removeComponent(int index)
        {
            if (index > this._componentItems.Count || index < 0)
            {
                //return -1;
                throw new IndexOutOfRangeException();
            }
            this._componentItems.RemoveAt(index);
            return 1;
        }

        public ProcessingItem getProcessing(int index)
        {
            if (index > this._processingItems.Count || index < 0)
            {
                //return new ProcessingItem();
                throw new IndexOutOfRangeException();
            }
            return this._processingItems[index];
        }

        public int ProcessingCount
        {
            get { return this._processingItems.Count; }
        }

        public int insertProcessing(ProcessingItem item)
        {
            this._processingItems.Add(item);
            return 1;
        }

        public int removeProcessing(int index)
        {
            if (index > this._processingItems.Count || index < 0)
            {
                //return -1;
                throw new IndexOutOfRangeException();
            }
            this._processingItems.RemoveAt(index);
            return 1;
        }

        public EProgrammingLanguage getProgrammingLanguage(int index)
        {
            if (index > this._programmingLanguages.Count || index < 0)
            {
                //return new EProgrammingLanguage(); 
                throw new IndexOutOfRangeException();
            }
            return this._programmingLanguages[index];
        }

        public int ProgrammingLanguagesCount
        {
            get { return this._programmingLanguages.Count; }
        }

        public int insertProgrammingLanguage(EProgrammingLanguage language)
        {
            this._programmingLanguages.Add(language);
            return 1;
        }

        public int removeProgrammingLanguage(int index)
        {
            if (index > this._programmingLanguages.Count || index < 0)
            {
                //return -1 ;
                throw new IndexOutOfRangeException();
            }
            this._programmingLanguages.RemoveAt(index);
            return 1;
        }

        public PotentialCouplingComponent getCouplingComponent(int index)
        {
            if (index > this._potentialComponents.Count || index < 0)
            {
                //return new PotentialCouplingComponent();
                throw new IndexOutOfRangeException();
            }
            return this._potentialComponents[index];
        }

        public int CouplingComponentsCount
        {
            get { return this._potentialComponents.Count; }
        }

        public int insertCouplingComponent(PotentialCouplingComponent item)
        {
            this._potentialComponents.Add(item);
            return 1;
        }

        public int removeCouplingComponent(int index)
        {
            if (index > this._potentialComponents.Count || index < 0)
            {
                //return -1;
                throw new IndexOutOfRangeException();
            }
            this._potentialComponents.RemoveAt(index);
            return 1;
        }

        public bool formatToXml(ref XmlElement modelClassExtentEle)
        {

            XmlDocument doc = modelClassExtentEle.OwnerDocument;
            XmlElement basicMetaDataEle = doc.CreateElement("BasicMetaData");
            modelClassExtentEle.AppendChild(basicMetaDataEle);

            //Alias Node
            XmlElement aliasRoot = doc.CreateElement("Alias");
            aliasRoot.InnerText = "";
            basicMetaDataEle.AppendChild(aliasRoot);
            for (int i = 0; i < this._alias.Count; i++)
            {
                XmlElement aliasEle = doc.CreateElement("Add");
                aliasEle.SetAttribute("value", this._alias[i]);
                aliasRoot.AppendChild(aliasEle);
            }

            //ApplicationDomains Node
            XmlElement domainRoot = doc.CreateElement("ApplicationDomains");
            domainRoot.InnerText = "";
            basicMetaDataEle.AppendChild(domainRoot);
            for (int i = 0; i < this._domains.Count; i++)
            {
                XmlElement domainEle = doc.CreateElement("Add");
                domainEle.SetAttribute("value", this._domains[i]);
                domainRoot.AppendChild(domainEle);
            }

            //Mechanism Node
            XmlElement mechanismRoot = doc.CreateElement("Mechanism");
            mechanismRoot.InnerText = "";
            basicMetaDataEle.AppendChild(mechanismRoot);
            for (int i = 0; i < this._mechanismItems.Count; i++)
            {
                XmlElement mechanismEle = doc.CreateElement("Add");
                mechanismEle.SetAttribute("name", this._mechanismItems[i].Name);
                mechanismEle.InnerText = this._mechanismItems[i].Value;
                mechanismRoot.AppendChild(mechanismEle);
            }

            //Methods Node
            XmlElement methodsRoot = doc.CreateElement("Methods");
            methodsRoot.InnerText = "";
            basicMetaDataEle.AppendChild(methodsRoot);
            for (int i = 0; i < this._methodItems.Count; i++)
            {
                XmlElement methodsEle = doc.CreateElement("Add");
                string type = this._methodItems[i].Type.ToString();
                type = type.Substring(type.IndexOf('_') + 1);
                //string type = "";
                //switch (this._methodItems[i].Type)
                //{
                //    case EMethodType.EMMT_Algorithm:
                //        type = "Algorithm";
                //        break;
                //    case EMethodType.EMMT_Formula:
                //        type = "Formula";
                //        break;
                //    case EMethodType.EMMT_Unknown:
                //        type = "Unknown";
                //        break;
                //}
                methodsEle.SetAttribute("name", this._methodItems[i].Name);
                methodsEle.SetAttribute("type", type);
                methodsEle.SetAttribute("value", this._methodItems[i].Value);
                methodsRoot.AppendChild(methodsEle);
            }

            //SpatiotemporalInfo Node
            this._spatialtemporalInfos.formatToXml(ref basicMetaDataEle);

            //Contributors Node
            XmlElement contributorsRoot = doc.CreateElement("Contributors");
            contributorsRoot.InnerText = "";
            basicMetaDataEle.AppendChild(contributorsRoot);
            for (int i = 0; i < this._contributors.Count; i++)
            {
                this._contributors[i].formatToXml(ref contributorsRoot);
            }

            //Components Node
            XmlElement componentsRoot = doc.CreateElement("Components");
            componentsRoot.InnerText = "";
            basicMetaDataEle.AppendChild(componentsRoot);
            for (int i = 0; i < this._componentItems.Count; i++)
            {
                XmlElement componentEle = doc.CreateElement("Add");
                componentEle.SetAttribute("name", this._componentItems[i].Name);
                componentEle.SetAttribute("description", this._componentItems[i].Description);
                componentEle.SetAttribute("url", this._componentItems[i].URL);
                componentsRoot.AppendChild(componentEle);
            }

            //Processing Node
            XmlElement processingRoot = doc.CreateElement("Processing");
            processingRoot.InnerText = "";
            basicMetaDataEle.AppendChild(processingRoot);
            for (int i = 0; i < this._processingItems.Count; i++)
            {
                XmlElement processingEle = doc.CreateElement("Add");
                string type = this._processingItems[i].Type.ToString();
                type = type.Substring(type.IndexOf('_') + 1);
                //switch (this._processingItems[i].Type)
                //{
                //    case EProcessingType.EPT_Postprocessing:
                //        type = "Postprocessing";
                //        break;
                //    case EProcessingType.EPT_Preprocessing:
                //        type = "Preprocessing";
                //        break;
                //    case EProcessingType.EPT_Visualization:
                //        type = "Visualization";
                //        break;
                //    case EProcessingType.ERP_Other:
                //        type = "Other";
                //        break;
                //}
                processingEle.SetAttribute("name", this._processingItems[i].Name);
                processingEle.SetAttribute("type", type);
                processingEle.SetAttribute("description", this._processingItems[i].Description);
                processingEle.SetAttribute("url", this._processingItems[i].URL);
                processingRoot.AppendChild(processingEle);
            }

            //TechnicalInfo Node
            XmlElement technicalInfoEle = doc.CreateElement("TechnicalInfo");
            basicMetaDataEle.AppendChild(technicalInfoEle);
            XmlElement programmingLanguagesRoot = doc.CreateElement("ProgrammingLanguages");
            programmingLanguagesRoot.InnerText = "";
            technicalInfoEle.AppendChild(programmingLanguagesRoot);
            for (int i = 0; i < this._programmingLanguages.Count; i++)
            {
                XmlElement programmingLanguageEle = doc.CreateElement("Add");
                string type = this._programmingLanguages[i].ToString();
                type = type.Substring(type.IndexOf('_') + 1);
                programmingLanguageEle.SetAttribute("value", type);
                programmingLanguagesRoot.AppendChild(programmingLanguageEle);
            }

            //PotentialCoupingInformation Node
            XmlElement potentialCouplingInformationEle = doc.CreateElement("PotentialCouplingInformation");
            basicMetaDataEle.AppendChild(potentialCouplingInformationEle);
            XmlElement couplingComponentsRoot = doc.CreateElement("CouplingComponents");
            couplingComponentsRoot.InnerText = "";
            potentialCouplingInformationEle.AppendChild(couplingComponentsRoot);
            for (int i = 0; i < this._potentialComponents.Count; i++)
            {
                XmlElement couplingComponentEle = doc.CreateElement("CouplingComponent");
                couplingComponentEle.SetAttribute("name", this._potentialComponents[i].Name);
                couplingComponentEle.SetAttribute("description", this._potentialComponents[i].Description);
                couplingComponentEle.SetAttribute("url", this._potentialComponents[i].URL);
                couplingComponentsRoot.AppendChild(couplingComponentEle);

                XmlElement cMethodsRoot = doc.CreateElement("Methods");
                cMethodsRoot.InnerText = "";
                for (int j = 0; j < this._potentialComponents[i].List_Methods.Count; j++)
                {
                    XmlElement cMethodsEle = doc.CreateElement("Add");
                    cMethodsEle.SetAttribute("value", this._potentialComponents[i].List_Methods[j]);
                    cMethodsRoot.AppendChild(cMethodsEle);
                }
                couplingComponentEle.AppendChild(cMethodsRoot);
            }

            return true;
            
        }

        public bool loadXml(XmlElement basicMetaData)
        {
            //Alias
            XmlElement aliasRoot = (XmlElement)basicMetaData.SelectSingleNode("Alias");
            foreach (XmlNode aliaNode in aliasRoot.ChildNodes)
            {
                XmlElement aliaEle = (XmlElement)aliaNode;
                this._alias.Add(aliaEle.GetAttribute("value"));
            }

            //Domains
            XmlElement domainsRoot = (XmlElement)basicMetaData.SelectSingleNode("ApplicationDomains");
            foreach (XmlNode domainNode in domainsRoot.ChildNodes)
            {
                XmlElement domainEle = (XmlElement)domainNode;
                this._domains.Add(domainEle.GetAttribute("value"));
            }

            //mechanism
            XmlElement mechanismRoot = (XmlElement)basicMetaData.SelectSingleNode("Mechanism");
            foreach (XmlNode mechanismNode in mechanismRoot.ChildNodes)
            {
                XmlElement mechainsmEle = (XmlElement)mechanismNode;
                string name = mechainsmEle.GetAttribute("name");
                string value = mechainsmEle.InnerText;
                MechanismItem mi = new MechanismItem(name, value);
                this._mechanismItems.Add(mi);
            }

            //methods
            XmlElement methodsRoot = (XmlElement)basicMetaData.SelectSingleNode("Methods");
            foreach (XmlNode methodNode in methodsRoot.ChildNodes)
            {
                XmlElement methodEle = (XmlElement)methodNode;
                string name = methodEle.GetAttribute("name");
                string strType = methodEle.GetAttribute("type");
                string value = methodEle.GetAttribute("value");
                EMethodType type = new EMethodType();
                //遍历枚举类型的值，获取该枚举值
                foreach (EMethodType mType in Enum.GetValues(typeof(EMethodType)))
                {
                    string strMType = mType.ToString();
                    strMType = strMType.Substring(strMType.IndexOf('_') + 1);
                    if (strType == strMType)
                    {
                        type = mType;
                        break;
                    }
                }
                MethodItem mi = new MethodItem(name,type,value);
                this._methodItems.Add(mi);
            }

            //spatiotemporalInfo
            XmlElement spatiotemporalInfoEle = (XmlElement)basicMetaData.SelectSingleNode("SpatiotemporalInfo");
            this._spatialtemporalInfos.loadXml(spatiotemporalInfoEle);

            //contributors
            XmlElement contributorsRoot = (XmlElement)basicMetaData.SelectSingleNode("Contributors");
            foreach (XmlNode contributorNode in contributorsRoot.ChildNodes)
            {
                XmlElement contributorEle = (XmlElement)contributorNode;
                Contributor contributor = new Contributor();
                contributor.loadXml(contributorEle);
                this._contributors.Add(contributor);
            }
            

            //components
            XmlElement componentsRoot = (XmlElement)basicMetaData.SelectSingleNode("Components");
            foreach (XmlNode componentNode in componentsRoot.ChildNodes)
            {
                XmlElement componentEle = (XmlElement)componentNode;
                string name = componentEle.GetAttribute("name");
                string description = componentEle.GetAttribute("description");
                string url = componentEle.GetAttribute("url");
                ComponentItem ci = new ComponentItem(name,description,url);
                this._componentItems.Add(ci);
            }
            

            //processing
            XmlElement processingRoot = (XmlElement)basicMetaData.SelectSingleNode("Processing");
            foreach (XmlNode processingNode in processingRoot.ChildNodes)
            {
                XmlElement processingEle = (XmlElement)processingNode;
                string name = processingEle.GetAttribute("name");
                string strType = processingEle.GetAttribute("type");
                string description = processingEle.GetAttribute("description");
                string url = processingEle.GetAttribute("url");

                EProcessingType type = new EProcessingType();
                foreach (EProcessingType eType in Enum.GetValues(typeof(EProcessingType)))
                {
                    string strPType = eType.ToString();
                    strPType = strPType.Substring(strPType.IndexOf('_') + 1);
                    if (strType == strPType)
                    {
                        type = eType;
                        break;
                    }
                }
                ProcessingItem pi = new ProcessingItem(name, type, description, url);
                this._processingItems.Add(pi);
            }

            //technicalInfo
            XmlElement languagesRoot = (XmlElement)basicMetaData.SelectSingleNode("TechnicalInfo").SelectSingleNode("ProgrammingLanguages");
            foreach (XmlNode languageNode in languagesRoot.ChildNodes)
            {
                XmlElement languageEle = (XmlElement)languageNode;
                string strValue = languageEle.GetAttribute("value");
                EProgrammingLanguage value = new EProgrammingLanguage();
                foreach (EProgrammingLanguage eValue in Enum.GetValues(typeof(EProgrammingLanguage)))
                {
                    string strPValue = eValue.ToString();
                    strPValue = strPValue.Substring(strPValue.IndexOf('_') + 1);
                    if (strValue == strPValue)
                    {
                        value = eValue;
                        break;
                    }
                }
                this._programmingLanguages.Add(value);                
            }

            //potentialCouplingInformation
            XmlElement couplingComponentsRoot = (XmlElement)basicMetaData.SelectSingleNode("PotentialCouplingInformation").SelectSingleNode("CouplingComponents");
            foreach (XmlNode couplingComponentNode in couplingComponentsRoot.ChildNodes)
            {
                XmlElement componentEle = (XmlElement)couplingComponentNode;
                string name = componentEle.GetAttribute("name");
                string description = componentEle.GetAttribute("description");
                string url = componentEle.GetAttribute("url");
                List<string> methods = new List<string>();
                XmlElement cMethodsRoot = (XmlElement)componentEle.SelectSingleNode("Methods");
                foreach (XmlNode methodNode in cMethodsRoot.ChildNodes)
                {
                    XmlElement methodEle = (XmlElement)methodNode;
                    methods.Add(methodEle.GetAttribute("value"));
                }
                PotentialCouplingComponent pcc = new PotentialCouplingComponent(name, description, url, methods);
                this._potentialComponents.Add(pcc);
            }

            return true;
        }
    }

    public class ExtendedMeta : IExtendedMeta
    {
        private Dictionary<string, string> _values;

        private Dictionary<string, IExtendedMeta> _groups;

        private IExtendedMeta _parent = null;

        public ExtendedMeta()
        {
            this._values = new Dictionary<string,string>();
            this._groups = new Dictionary<string,IExtendedMeta>();
            this._parent = null;
        }

        public bool addValue(string key, string value)
        {
            if (this.isKeyExisting(key))
            {
                return false;
            }
            this._values.Add(key, value);
            return true;
        }

        public bool addGroup(string key, IExtendedMeta group)
        {
            if (this.isKeyExisting(key))
            {
                return false;
            }
            this._groups.Add(key, group);
            return true;
        }

        public bool isKeyExisting(string key)
        {
            if (!this._values.ContainsKey(key) && !this._groups.ContainsKey(key))
                return false;
            return true;
        }

        public bool removeKey(string key)
        {
            if (this.isKeyExisting(key))
            {
                return false;
            }
            if (this.getKeyType(key) == EExtendedType.EET_Value)
            {
                this._values.Remove(key);
                return true;
            }
            else if (this.getKeyType(key) == EExtendedType.EET_Group)
            {
                this._groups.Remove(key);
                return true;
            }
            return false;
        }

        public EExtendedType getKeyType(string key)
        {
            if (this._values[key] != null)
            {
                return EExtendedType.EET_Value;
            }
            else if (this._groups[key] != null)
            {
                return EExtendedType.EET_Group;
            }
            return EExtendedType.EET_Unknown;
        }

        public string getValue(string key)
        {
            if (this._values[key] != null)
            {
                return this._values[key];
            }
            return "";
        }

        public IExtendedMeta getGroup(string key)
        {
            if (this._groups[key] != null)
            {
                return this._groups[key];
            }
            return null;
        }

        public List<string> getAllValueKeys()
        {
            return this._values.Keys.ToList();
        }

        public List<string> getAllGroupKeys()
        {
            return this._groups.Keys.ToList();
        }

        public IExtendedMeta Root
        {
            get 
            {
                IExtendedMeta emeta = this;
                while (emeta.Parent != null)
                {
                    emeta = emeta.Parent;
                }
                return emeta;
            }
        }

        public IExtendedMeta Parent
        {
            get { return this._parent; }
        }

        public bool formatToXml(ref XmlElement extendedmeta, string key = "")
        {
            XmlDocument doc = extendedmeta.OwnerDocument;

            XmlElement extendedMetaDataEle = doc.CreateElement("ExtendedGourp");
            extendedmeta.SetAttribute("key", key);
            extendedmeta.AppendChild(extendedMetaDataEle);

            List<string> list_valueKeys = this.getAllValueKeys();
            for (int i = 0; i < list_valueKeys.Count; i++)
            {
                XmlElement addMetaDataEle = doc.CreateElement("Add");
                addMetaDataEle.SetAttribute("key", list_valueKeys[i]);
                addMetaDataEle.SetAttribute("value", this.getValue(list_valueKeys[i]));

                extendedmeta.AppendChild(addMetaDataEle);
            }

            List<string> list_groupKeys = this.getAllGroupKeys();
            for (int i = 0; i < list_groupKeys.Count; i++)
            {
                XmlElement groupMetaDataEle = doc.CreateElement("ExtendedGroup");
                groupMetaDataEle.SetAttribute("key", list_groupKeys[i]);

                IExtendedMeta pEMeta = this.getGroup(list_groupKeys[i]);

                pEMeta.formatToXml(ref groupMetaDataEle, list_groupKeys[i]);
                extendedmeta.AppendChild(groupMetaDataEle);
            }

            return true;
        }

        public bool loadXml(XmlElement extendedmeta)
        {
            int count = extendedmeta.ChildNodes.Count;

            for (int i = 0; i < count; i++)
            {
                XmlElement node = extendedmeta.ChildNodes[i] as XmlElement;
                if (node.Name == "ExtendedGroup")
                {
                    string key = node.GetAttribute("key");
                    IExtendedMeta pExtendedMeta = new ExtendedMeta();
                    pExtendedMeta.loadXml(node);
                    this.addGroup(key, pExtendedMeta);
                }
                else if (node.Name == "Add")
                {
                    string key = node.GetAttribute("key");
                    string value = node.GetAttribute("value");
                    this.addValue(key, value);
                }
            }

            return true;
        }
    }

    public class MetaDataDocument : IMetaDataDocument
    {
        private IBasicMeta _basicMeta = new BasicMeta();
        //private ExtendMeta _extenMeta = new ExtendMeta();
        private IExtendedMeta _extendMeta = new ExtendedMeta();
        
        public IBasicMeta getBasicMetaData()
        {
            return this._basicMeta;
        }

        public IExtendedMeta getExtentMetaData()
        {
            return this._extendMeta;
        }

        public string format2Stream()
        {
            string xmlStr;
            XmlDocument doc = new XmlDocument();
            XmlElement modelClassExtentEle = doc.CreateElement("ModelClassExtent");
            doc.AppendChild(modelClassExtentEle);
            this._basicMeta.formatToXml(ref modelClassExtentEle);
            this._extendMeta.formatToXml(ref modelClassExtentEle);
           
            xmlStr = doc.InnerXml;
            return xmlStr;
        }

        public int format2File(string filepath)
        {
            XmlDocument doc = new XmlDocument();
            XmlElement modelClassExtentEle = doc.CreateElement("ModelClassExtent");
            doc.AppendChild(modelClassExtentEle);
            this._basicMeta.formatToXml(ref modelClassExtentEle);
            this._extendMeta.formatToXml(ref modelClassExtentEle);

            doc.Save(filepath);
            return 1;
        }

        public int loadStream(string stream)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(stream);
            XmlElement modelClassExtentEle = doc.DocumentElement;
            XmlElement basicMetaDataEle = (XmlElement)modelClassExtentEle.SelectSingleNode("BasicMetaData");
            XmlElement extendMetaDataEle = (XmlElement)modelClassExtentEle.SelectSingleNode("ExtendMateData");


            return 1;
        }

        public int loadFile(string filepath)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(filepath);
            XmlElement modelClassExtentEle = doc.DocumentElement;
            modelClassExtentEle = (XmlElement)modelClassExtentEle.SelectSingleNode("MateData");
            XmlElement basicMetaDataEle = (XmlElement)modelClassExtentEle.SelectSingleNode("BasicMetaData");
            XmlElement extendMetaDataEle = (XmlElement)modelClassExtentEle.SelectSingleNode("ExtendedMateData");
            this._basicMeta.loadXml(basicMetaDataEle);
            this._extendMeta.loadXml(extendMetaDataEle);

            return 1;
        }
    }
}
